///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_IO_CFILEIMPL_H_
#define _BUOLA_IO_CFILEIMPL_H_

#include <buola/buola.h>
#include <buola/utility/uevent.h>

#include <buola/datetime/clocks.h>
#include <buola/io/curi.h>
#include <buola/io/cfilefilter.h>
#include "cfdstream.h"

#include <unordered_set>

namespace buola { namespace io {

///\addtogroup filesystem
///@{

////////////////////////////////////////////////////////////////////////////

/// file

/// A file is anything which has a name (identified by an URL)
/// and either you can obtain a stream to read from or write data to it,
/// or contains other files (in this case it is also a folder)
///
/// An http address is a file (you can read data from it)
/// A socket is not a file (it has no URL)
///
////////////////////////////////////////////////////////////////////////////

class CFileImpl : public UShared
{
protected:
///\name constructor and destructor
//@{
    ///initializes the file object with a URL
    CFileImpl(const CURI &pURI)
        :   mURI(pURI)
    {}

    ///destructor
    virtual ~CFileImpl() {}
//@}

public:
///\name file information access
//@{
    ///returns the URI for the file
    const CURI &GetURI()        {   return mURI;    }
    
    virtual CURI GetTarget()=0;
    
    ///returns the access time
    virtual CCalendarTime GetAccessTime()=0;
    ///returns the creation time
    virtual CCalendarTime GetCreationTime()=0;
    ///returns the modification time
    virtual CCalendarTime GetModificationTime()=0;

    ///returns the file type
    virtual EFileType GetType()=0;

    ///returns the file size
    virtual ssize_t GetSize()=0;

    ///returns the file owner
    virtual os::CUser GetOwner()=0;
    ///returns the file user group
    virtual os::CGroup GetGroup()=0;

    ///returns the access permissions for the file
    virtual EPermission GetPermission()=0;
//@}
    
public:
///\name file system manipulation
//@{
    ///true if the current user can read the file
    virtual bool CanRead()=0;
    ///true if the current user can write to the file
    virtual bool CanWrite()=0;
    ///true if the current user can execute the file
    virtual bool CanExecute()=0;

    ///true if the current user can change ownership of the file
    virtual bool CanChangeOwner()=0;
    ///true if the current user can change group of the file
    virtual bool CanChangeGroup()=0;
    ///true if the current user can change permissions for the file
    virtual bool CanChangePermissions()=0;
//@}

///\name related objects
//@{
    ///returns a stream to the file
    virtual PStream GetStream(io::EMode pMode,io::EPermission pPermission)=0;

    ///returns the folder where the file is contained
    CFolder *GetParent()
    {
        return nullptr;
    }
//@}

///\name directory access
//@{
    ///returns a vector with all children of this file (if the file is a folder)
    virtual std::vector<CFile> GetChildren(PFileFilter pFilter=nullptr)=0;
    ///returns a vector with the names of all children
    virtual std::vector<std::string> GetChildrenNames(PFileFilter pFilter=nullptr);
    ///returns a set with the names of all children
    virtual std::unordered_set<std::string> GetChildrenSet(PFileFilter pFilter=nullptr);
    ///returns a vector with the names of all children
    virtual std::vector<io::CURI> GetChildrenURIs(PFileFilter pFilter=nullptr);
    ///returns true if the folder has any children matching the filter
    virtual bool HasChildren(PFileFilter pFilter=nullptr);
//@}
    
private:
    CURI mURI;
};

///@}

/*namespace io*/ } /*namespace buola*/ }

#endif
